#! /bin/sh
##
## %CopyrightBegin%
## 
## Copyright Ericsson AB 2009-2016. All Rights Reserved.
## 
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
##     http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
## 
## %CopyrightEnd%
##
#

#
## run-named
## 
## $0 IPAddress PortNum SubDir
##
## * Create a work directory ./SubDir, create a named.conf there.
## * Locate named and check its version.
## * Zopy zone files from `dirname $0`/SubDir to ./SubDir.
## * Start named in ./SubDir with logging to named.log there.
## * Wait for "quit" on stdin.
## * Terminate named and wait for it.
##
## Prints status lines starting with tag and colon (think mail header):
##   Error: have given up, no name server started
##   Running: name server is running, waiting for "quit"
##   Other tags: diagnostics info
#

unset LDPATH CDPATH ENV BASH_ENV
IFS=' 	'
PATH=/usr/sbin:/sbin:/usr/bin:/bin
SHELL=/bin/sh
export PATH SHELL

CONF_FILE=named.conf
INC_FILE=named_inc.conf
PID_FILE=named.pid
LOG_FILE=named.log

error () {
    r=$?
    echo "Error: $*"
    exit $r
}

# Check argument: IP address
test :"$1" != : || \
    error "Empty argument 1: IP address !"

# Check argument: Port number
expr "0$2" + 0 '>' 0  '&'  "0$2" + 0 '<' 65536 >/dev/null 2>&1 || \
    error "Invalid argument 2: port number !"

# Check argument: Work/Zone subdir
test :"$3" != : || \
    error "Empty argument 3: Work/Zone subdir!"
SRCDIR="`dirname "$0"`/$3"
test -d "$SRCDIR" || \
    error "Missing zone directory $SRCDIR !"
test -f "$SRCDIR/$INC_FILE" || \
    error "Missing file: $SRCDIR/$INC_FILE !"

# Locate named and check version.
# The bind-named name is used for tricking Apparmor and such
# by copying/hardlinking the real named to that name.
NAMED=named
for n in /usr/local/bin/bind-named /usr/local/bin/named \
    /usr/sbin/bind-named /usr/sbin/named /usr/sbin/in.named
do
    test -x "$n" && NAMED="$n" && break
done
NAMED_VER="`"$NAMED" -v 2>&1`" || \
    error "Name server not found!"
NAMED_VER=`echo "$NAMED_VER" | ( read V1 V2 V3 IGNORED && \
    if test :"$V1" = :'in.named'; then
	echo "$V2 $V3"
    else
	echo "$V1 $V2"
    fi
)`
case :"$NAMED_VER" in
    :'BIND '8.*) NAMED_FG='-f';;
    :'BIND '9.*) NAMED_FG='-g';;
    :*) error "Name server version is unknown: $NAMED_VER";;
esac

# Create working directory and cd to it
mkdir "$3" >/dev/null 2>&1
cd "$3" >/dev/null 2>&1 || \
    error "Can not cd: $3 !"

# Create $CONF_FILE
cat >"$CONF_FILE" <<-CONF_FILE
	#
	# $CONF_FILE for $NAMED_VER
	# Generated by $0.
	# 
	# Copyright: see $0.
	#
	logging {
	    category default {
	        default_stderr;
	    };
	};
	CONF_FILE
case :"$NAMED_VER" in
    :'BIND '8.*|:'BIND '9.[012]|:'BIND '9.[012].*)
		cat >>"$CONF_FILE" <<-CONF_FILE
	controls {
	    inet 127.0.0.1 port 0 allow { !0/32; };
	};
	options {
	    pid-file "$PID_FILE";
	    listen-on port $2 { $1; };
	    recursion no;
	    allow-query { $1; };
	};
	CONF_FILE
	;;
    :*)
		cat >>"$CONF_FILE" <<-CONF_FILE
	controls {
	};
	options {
	    pid-file none;
	    listen-on port $2 { $1; };
	    recursion no;
	    allow-query { $1; };
	};
	CONF_FILE
	;;
esac
cat >>"$CONF_FILE" <<-CONF_FILE
	include "$INC_FILE";
	CONF_FILE

# Copy all subdir files
( cd "$SRCDIR" && ls -1 ) | while read f; do
    cp -fp "$SRCDIR/$f" .
done

# Start nameserver
echo "Cwd: `pwd`"
echo "Nameserver: $NAMED_VER"
echo "Port: $2"
echo "ZoneDir: $3"
echo "Command: $NAMED $NAMED_FG -c $CONF_FILE"
$NAMED $NAMED_FG -c "$CONF_FILE" >"$LOG_FILE" 2>&1 </dev/null &
NAMED_PID=$!
echo "Pid: $NAMED_PID"
trap "kill $NAMED_PID >/dev/null 2>&1; wait $NAMED_PID >/dev/null 2>&1" \
    0 1 2 3 15

sleep 5 # Give name server time to load its zone files

if ps -p $NAMED_PID >/dev/null 2>&1 || ps p $NAMED_PID >/dev/null 2>&1; then
    echo "Running: Enter \`\`quit'' to terminate nameserver[$NAMED_PID]..."
    while read LINE; do
	test :"$LINE" = :'quit' && break
    done
    echo "Closing: Terminating nameserver..."
else
    error "$NAMED failed to start"
fi
